<?php

namespace App\Task;

use App\Model\DataAdEcpmBackhaul;
use App\Model\DataBackhaulSetting;
use App\Model\DataPaymentBackhaul;
use App\Model\DataSpread;
use App\Model\DataAdEcpm;
use App\Model\Payment;
use GuzzleHttp\Client;
use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\DbConnection\Db;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Utils\ApplicationContext;
use Psr\Log\LoggerInterface;



class BackhaulDyEcpmTask
{
    protected LoggerInterface $logger;

    public static $reportUrl = "https://analytics.oceanengine.com/api/v2/conversion";
    public function __construct(protected LoggerFactory $loggerFactory)
    {
        $this->logger = $this->loggerFactory->get('log', 'BackhaulDyEcpm');
    }

    public function execute()
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\RedisFactory::class)->get('default');

        $this->logger->info(date('Y-m-d H:i:s') . '------------------------定时获取redis上的数据');
        $this->logger->info('开始获取用户未处理的数据');
        $start_date = date('Y-m-d 00:00:00',time());
        $end_date = date('Y-m-d 23:59:59',time());
//        return;
        $handleKey = 'dy_backhaul_ecpm_live_qualify';
        try {

            $keyData = $redis->get($handleKey);
            if(!empty($keyData)){

                $this->logger->info('存在处理中的ecpm qualify订单进程');
                $this->logger->info(date('Y-m-d H:i:s') . '------------------------结束定时获取qualify订单进行上报');
                return;
            }else{
                $redis->set($handleKey,1);
            }
            Db::beginTransaction();
            //获取需要处理的订单
            $adEcpmData = DataAdEcpm::query()
                ->select('data_ad_ecpm.applet_id','data_ad_ecpm.spread_id','data_ad_ecpm.user_id',Db::raw('count(data_ad_ecpm.user_id) as count_user'))
                ->where('event_time','>=',$start_date)
                ->where('event_time','<=',$end_date)
                ->leftJoin('data_spread','data_spread.id','=','data_ad_ecpm.spread_id')
                ->leftJoin('data_backhaul_setting','data_backhaul_setting.id','=','data_spread.backhaul_setting_id')
                ->leftJoin('data_ad_ecpm_backhaul',function ($join) use($start_date,$end_date){
                    $join->on('data_ad_ecpm_backhaul.applet_id', '=', 'data_ad_ecpm.applet_id')
                        ->on('data_ad_ecpm_backhaul.spread_id', '=', 'data_ad_ecpm.spread_id')
                        ->on('data_ad_ecpm_backhaul.user_id', '=', 'data_ad_ecpm.user_id')
                        ->where('data_ad_ecpm_backhaul.created_at','>=',$start_date)
                        ->where('data_ad_ecpm_backhaul.created_at','<=',$end_date)
                        ->where('data_ad_ecpm_backhaul.type',2);
                })
                ->whereRaw('event_time > data_backhaul_setting.updated_at')
                ->whereNull('data_ad_ecpm_backhaul.id')
                ->groupBy(['data_ad_ecpm.applet_id','data_ad_ecpm.spread_id','data_ad_ecpm.user_id'])
                ->get()->toArray();
            if(!empty($adEcpmData)) {
                //判断是否
                $this->logger->info('订单的数据为数量为：', [count($adEcpmData)]);
                $errorMeg = [];
                foreach ($adEcpmData as $adEcpmDatum) {

//                    var_dump($adEcpmDatum);exit();
                    //判断是否
                    $userInfo = Db::table('data_user_' . $adEcpmDatum['applet_id'])->where(['id' => $adEcpmDatum['user_id']])->first();
                    $this->logger->info('获取订单的用户user,id为:', [$userInfo->id]);
                    if (!empty($userInfo)) {

                        $this->logger->info('获取订单对应的推广链接,最新的推广链ID:', [$adEcpmDatum['spread_id']]);
                        $spreadInfo = DataSpread::query()->where(['id' => $adEcpmDatum['spread_id']])->first();
                        if (!empty($spreadInfo)) {

                            $backhaulsettingInfo = DataBackhaulSetting::query()->where(['id' => $spreadInfo->backhaul_setting_id])->first();
                            if (!empty($backhaulsettingInfo)) {
                                if(!empty($userInfo->click_id) && $userInfo->click_id != 'undefined' && $backhaulsettingInfo->operation_mode == 2) {
                                    //先获取订单的推广链接ID
                                    $this->logger->info('获取订单所对应的推广最新的回传token', [$userInfo->id]);
                                    $this->handOrder($redis, $adEcpmDatum, $userInfo, $spreadInfo,$backhaulsettingInfo);
                                }
                            }
                        }
                    }
                }
            }else{
                $this->logger->info('没有Ecpm qualify订单需要上报');
            }

            $redis->del($handleKey);
            Db::commit();
        }catch (\Exception $e){
            $redis->del($handleKey);
            $this->logger->error('请求qualify回传|错误：' . $e->getLine() . '|' . $e->getMessage());
            Db::rollBack();
        }
        $this->logger->info(date('Y-m-d H:i:s') . '------------------------结束定时获取Ecpm qualify订单进行上报');
    }

    public function handOrder($redis,$adEcpmDatum,$userInfo,$spreadInfo,$backhaulsettingInfo){

        $start_date = date('Y-m-d 00:00:00',time());
        $end_date = date('Y-m-d 23:59:59',time());
        //判断回传配置中是否需要回传
        $ipu_qualify = $backhaulsettingInfo->ipu_qualify;
        $this->logger->info('判断回传配置首日广告展示达标数',[$ipu_qualify]);
        if(!empty($ipu_qualify)){
            //判断用户的染色时间是否为今天
            $this->logger->info('判断用户的染色时间是否为今天',[$userInfo->dyeing_time]);
            if($start_date <= $userInfo->dyeing_time && $end_date >= $userInfo->dyeing_time) {
                if($adEcpmDatum['count_user'] >= $ipu_qualify){

                    $ecpmKey = 'ecpm_show_'.$spreadInfo->id.'_'.$userInfo->applet_id.'_'.$backhaulsettingInfo->id;
                    $backhaul_filterate_num = $backhaulsettingInfo->backhaul_filterate_num;
                    $backhaul_filterate_miss = $backhaulsettingInfo->backhaul_filterate_miss;
                    if($backhaul_filterate_num == 0 && $backhaul_filterate_miss == 0) {

                        $this->logger->info('订单回传规则 每几单漏几单都为0，此订单不回传:', [$backhaul_filterate_num, $backhaul_filterate_miss]);
                        $this->installRel($userInfo,$adEcpmDatum,$backhaulsettingInfo,3,$adEcpmDatum['count_user'],'',0,3);
                    }else{
                        //判断回传过滤逻辑 每几单，漏几单
                        $this->logger->info('判断回传过滤逻辑 每几单，漏几单:',[$backhaul_filterate_num,$backhaul_filterate_miss]);
                        $backhaul_key = $ecpmKey.'_'.$backhaul_filterate_num.'_'.$backhaul_filterate_miss;
                        if($redis->exists($backhaul_key) == 0){
                            //删除之前属于此用户的回传key
                            $old_key = $redis->keys($ecpmKey.'*');
                            if(!empty($old_key)){
                                $redis->del($old_key);
                            }
                            $redis->hSet($backhaul_key,'backhaul_filterate_num',$backhaul_filterate_num);
                            $redis->hSet($backhaul_key,'backhaul_filterate_miss',$backhaul_filterate_miss);
                        }
                        $redis_backhaul_num = $redis->hGet($backhaul_key,'backhaul_filterate_num');
                        $redis_backhaul_miss = $redis->hGet($backhaul_key,'backhaul_filterate_miss');
                        if(intval($redis_backhaul_miss) == 0 && intval($redis_backhaul_num) == 0){
                            $this->logger->info('漏单和上传订单都为0时，重新设置回传规则',[]);
                            $redis->hSet($backhaul_key,'backhaul_filterate_num',$backhaul_filterate_num);
                            $redis->hSet($backhaul_key,'backhaul_filterate_miss',$backhaul_filterate_miss);
                            $redis_backhaul_num = $backhaul_filterate_num;
                            $redis_backhaul_miss = $backhaul_filterate_miss;
                        }
                        if($redis_backhaul_num != 0) {
                            $this->logger->info('此用户为需要回传用户:', [$userInfo->id]);
                            $uploadData = $this->uploadPayment($userInfo);
                            if ($uploadData) {
                                $this->logger->info('上报回传成功:', [$adEcpmDatum['user_id']]);
                                $redis->hIncrBy($backhaul_key,'backhaul_filterate_num',-1);
                                $execution_num = $backhaul_filterate_num -$redis_backhaul_num;
                                $this->installRel($userInfo,$adEcpmDatum,$backhaulsettingInfo,2,$adEcpmDatum['count_user'],$backhaul_key,intval($execution_num+1),1);
                            }
                        }else{
                            if($redis_backhaul_miss != 0){
                                $this->logger->info('此订单为漏单，不上报回传,减少redis中的值',[$adEcpmDatum['user_id']]);
                                $num = $redis_backhaul_miss-1;
                                $redis->hSet($backhaul_key,'backhaul_filterate_miss',intval($num));
                                $this->logger->info('此订单为漏单，不上报回传',[$redis->hGet($backhaul_key,'backhaul_filterate_miss')]);
                                $execution_num = $backhaul_filterate_miss - $num;
                                $this->installRel($userInfo,$adEcpmDatum,$backhaulsettingInfo,2,$adEcpmDatum['count_user'],$backhaul_key,intval($execution_num),2);
                            }
                        }
                    }
                }
            }
        }
    }

    public function installRel($userInfo,$adEcpmInfo,$backhaulsettingInfo,$type=1,$jud_value=0,$redis_key='',$execution_num=0,$backhaul_type=1){


        $open_id = $userInfo->xc_open_id ?? '';
        $ad_id = $userInfo->ad_id ?? '';
        $clue_token = $userInfo->clue_token  ?? '';
        $click_id =$userInfo->click_id ?? '';

        DataAdEcpmBackhaul::create([
            'user_id' => $userInfo->id,
            'applet_id' => $adEcpmInfo['applet_id'],
            'ad_ecpm_id' => 0,
            'xc_open_id' => $open_id,
            'click_id' => $click_id,
            'redis_key' => $redis_key,
            'type' => $type,
            'backhaul_setting_id' => $backhaulsettingInfo->id,
            'jud_value' => $jud_value,
            'spread_id' => $adEcpmInfo['spread_id'],
            'execution_num' =>$execution_num,
            'backhaul_type' =>$backhaul_type,
        ]);
    }
    public function uploadPayment($userInfo){


        $click_id =$userInfo->click_id;
        try {

            $params = [
                "context" =>
                    ["ad" =>[
                        'callback' => $click_id
                    ],
                    ],
                "event_type"  => "game_addiction",
//                "props" => [
//                    'pay_amount' => $paymentInfo->amount
//                ],
//                "timestamp" => time()*1000
            ];

            $linkUrl = self::$reportUrl;
            $this->logger->info('请求抖音上报Ecpm数据：'.PHP_EOL.var_export(['result' => $params], true));
            $this->logger->info('请求抖音上报EcpmUrl：'.$linkUrl);
            //开始上传
            $result  = $this->request($params, $linkUrl,'POST');
//            $result['code'] = 0;
            if($result['code'] == 0 ){
                $this->logger->info('调用抖音上报Ecpm接口成功 返回数据：'.PHP_EOL.var_export(['result' => $result], true));
                //插入订单回传关联表
                return true;
            }else{
                $this->logger->error('调用抖音上报Ecpm接口失败 返回数据：'.PHP_EOL.var_export(['result' => $result], true));
            }

        }catch (\Exception $e){

            $this->logger->error('请求回传|错误：' . $e->getLine() . '|' . $e->getMessage());
            return false;
        }

        return false;
    }
    /**
     * 传入数组进行HTTP POST请求
     */
    function request(array $params, string $url,string $method,string $access_token = null)
    {
        $client   = new Client([
            'timeout' => 3
        ]);
        $headers       = ['Content-Type' => 'application/json'];
        if(!empty($access_token)){
            $headers['access-token'] = $access_token;
        }

        $requestParams = [
            'headers' => $headers,
        ];
        if ($method == 'GET') {
            $requestParams['query'] = $params;
        } else {
            $requestParams['json'] = $params;//json_encode($params,JSON_UNESCAPED_UNICODE);
        }
        $response = $client->request($method,$url, $requestParams);
        if ($response->getStatusCode() !== 200) {
            return '';
        }
        $result   = $response->getBody()->getContents();
        $resultArr = json_decode($result,true);
        return $resultArr;

    }
}